package com.xuecheng.media.service.impl;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.vod.model.v20170321.GetPlayInfoRequest;
import com.aliyuncs.vod.model.v20170321.GetPlayInfoResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.media.model.dto.MediaDTO;
import com.xuecheng.api.media.model.qo.QueryMediaModel;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.enums.media.MediaAuditEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.media.common.constant.MediaErrorCode;
import com.xuecheng.media.common.utils.AliyunVODUtil;
import com.xuecheng.media.controller.MediaAuditController;
import com.xuecheng.media.convert.MediaConvert;
import com.xuecheng.media.entity.Media;
import com.xuecheng.media.mapper.MediaMapper;
import com.xuecheng.media.service.MediaService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 媒资信息 服务实现类
 * </p>
 *
 * @author 杨佳畅
 */
@Slf4j
@Service
public class MediaServiceImpl extends ServiceImpl<MediaMapper, Media> implements MediaService {

    @Value("${aliyun.region}")
    private String region;

    @Value("${aliyun.accessKeyId}")
    private String accessKeyId;

    @Value("${aliyun.accessKeySecret}")
    private String accessKeySecret;

    /**
     * 分页条件查询媒资列表
     *
     * @param params    分页信息
     * @param model     查询条件
     * @param companyId 公司ID
     * @return
     */
    @Override
    public PageVO<MediaDTO> queryMediaList(PageRequestParams params, QueryMediaModel model, Long companyId) {
        if (params.getPageNo() < 1) {
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        }
        if (params.getPageSize() < 1) {
            params.setPageSize(PageRequestParams.DEFAULT_PAGE_SIZE);
        }
        if (ObjectUtils.isEmpty(companyId)) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        // 封装对象，构建查询条件
        Page<Media> page = new Page<>(params.getPageNo(), params.getPageSize());
        LambdaQueryWrapper<Media> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtil.isNotBlank(model.getFilename()), Media::getFilename, model.getFilename());
        queryWrapper.eq(StringUtil.isNotBlank(model.getType()), Media::getType, model.getType());
        queryWrapper.eq(StringUtil.isNotBlank(model.getAuditStatus()), Media::getAuditStatus, model.getAuditStatus());
        // 如果传递companyId != OPERATION_FLAG 才会根据机构ID查询
        if (!(ObjectUtils.nullSafeEquals(companyId, MediaAuditController.OPERATION_FLAG))) {
            // 根据公司ID，精准查询
            queryWrapper.eq(Media::getCompanyId, companyId);
        }
        queryWrapper.orderByDesc(Media::getCreateDate);

        Page<Media> pageResult = this.page(page, queryWrapper);
        List<Media> records = pageResult.getRecords();
        long total = pageResult.getTotal();

        // 将数据转为DTO
        List<MediaDTO> dtos = Collections.emptyList();
        if (!CollectionUtils.isEmpty(records)) {
            dtos = new ArrayList<>();
            dtos = MediaConvert.INSTANCE.entity2dtos(records);
        }

        // 封装分页查询对象
        PageVO<MediaDTO> pageVO = new PageVO<>(dtos, total, params.getPageNo(), params.getPageSize());

        return pageVO;
    }

    /**
     * 保存媒资信息
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public MediaDTO createMedia(MediaDTO dto) {
        if (ObjectUtils.isEmpty(dto.getFileId()) || ObjectUtils.isEmpty(dto.getCompanyId()) || ObjectUtils.isEmpty(dto.getFilename())) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        // 初始化审核状态为未提交
        dto.setAuditStatus(MediaAuditEnum.AUDIT_UNPAST_STATUS.getCode());
        String playUrl = getPlayUrl(dto.getFileId());
        Media po = MediaConvert.INSTANCE.dto2entity(dto);
        // 设置视频播放地址
        po.setUrl(playUrl);
        boolean resultSave = this.save(po);
        if (!resultSave) {
            ExceptionCast.cast(MediaErrorCode.E_140001);
        }

        // 返回最新数据
        Media media = this.getById(po.getId());
        MediaDTO resultDTO = MediaConvert.INSTANCE.entity2dto(media);
        return resultDTO;
    }

    private String getPlayUrl(String videoId) {
        String playUrl = "";
        try {
            // 初始化客户端
            DefaultAcsClient client = AliyunVODUtil.initVodClient(region, accessKeyId, accessKeySecret);
            try {
                GetPlayInfoRequest request = new GetPlayInfoRequest();
                // 设置视频ID
                request.setVideoId(videoId);
                GetPlayInfoResponse response = client.getAcsResponse(request);
                GetPlayInfoResponse.PlayInfo playInfo = response.getPlayInfoList().get(0);
                //播放地址
                playUrl = playInfo.getPlayURL();
            } catch (Exception e) {
                log.error("获取视频播放源失败 => {}", e.getLocalizedMessage());
            }
        } catch (ClientException e) {
            log.error("获取视频播放源失败 => {}", e.getLocalizedMessage());
        }
        return playUrl;
    }

    // public String getPlayUrl(Long mediaId, Long companyId) {
    //     if (ObjectUtils.isEmpty(companyId)) {
    //         ExceptionCast.cast(CommonErrorCode.E_100101);
    //     }
    //     Media media = this.getById(mediaId);
    //     if (ObjectUtils.isEmpty(media)) {
    //         ExceptionCast.cast(MediaErrorCode.E_140005);
    //     }
    //     String videoId = media.getFileId();
    //     if (ObjectUtils.isEmpty(videoId)) {
    //         ExceptionCast.cast(MediaErrorCode.E_140013);
    //     }
    //
    //     String playUrl = media.getUrl();
    //     return playUrl;
    // }

    /**
     * 根据ID查询媒资信息，由微服务远程调用
     *
     * @param mediaId 媒资ID
     * @return
     */
    @Override
    public RestResponse<MediaDTO> getMediaById4Service(Long mediaId) {
        if (ObjectUtils.isEmpty(mediaId)) {
            return RestResponse.validfail(CommonErrorCode.E_100101);
        }
        Media media = this.getById(mediaId);
        // 判断是否存在
        if (ObjectUtils.isEmpty(media)) {
            return RestResponse.validfail(MediaErrorCode.E_140005);
        }
        MediaDTO mediaDTO = MediaConvert.INSTANCE.entity2dto(media);
        return RestResponse.success(mediaDTO);
    }

    @Override
    public void removeMediaById(Long mediaId, Long companyId) {
        if (ObjectUtils.isEmpty(mediaId) || ObjectUtils.isEmpty(companyId)) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        // 数据是否存在
        Media media = this.getById(mediaId);
        if (ObjectUtils.isEmpty(media)) {
            ExceptionCast.cast(MediaErrorCode.E_140005);
        }

        // 审核状态，只允许删除未提交、审核未通过的媒资
        String auditStatus = media.getAuditStatus();
        if (!MediaAuditEnum.AUDIT_UNPAST_STATUS.getCode().equals(auditStatus) ||
                !MediaAuditEnum.AUDIT_DISPAST_STATUS.getCode().equals(auditStatus)) {
            ExceptionCast.cast(MediaErrorCode.E_140008);
        }

        // TODO: 媒资被课程计划使用，不允许删除

        boolean result = this.removeById(mediaId);
        if (!result) {
            ExceptionCast.cast(MediaErrorCode.E_140002);
        }
    }

    /**
     * 审核媒资信息
     *
     * @param dto
     */
    @Override
    @Transactional
    public void approveMedia(MediaDTO dto) {
        if (ObjectUtils.isEmpty(dto.getId()) || ObjectUtils.isEmpty(dto.getAuditStatus()) || ObjectUtils.isEmpty(dto.getAuditMind())) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        Media media = this.getById(dto.getId());
        if (ObjectUtils.isEmpty(media)) {
            ExceptionCast.cast(MediaErrorCode.E_140005);
        }

        // 只能审核已提交的媒资
        // 如果是未提交，则对此进行审核，因为前端暂时没有提交媒资按钮
        if (!MediaAuditEnum.AUDIT_UNPAST_STATUS.getCode().equals(media.getAuditStatus())) {
            ExceptionCast.cast(MediaErrorCode.E_140008);
        }

        LambdaUpdateWrapper<Media> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Media::getAuditStatus, dto.getAuditStatus());
        updateWrapper.set(Media::getAuditMind, dto.getAuditMind());
        updateWrapper.set(Media::getChangeDate, LocalDateTime.now());
        updateWrapper.eq(Media::getId, dto.getId());
        boolean updateResult = this.update(updateWrapper);
        if (!updateResult) {
            ExceptionCast.cast(MediaErrorCode.E_140009);
        }


    }

    /**
     * 预览媒资信息
     *
     * @param mediaId 媒资ID
     * @return 媒资URL
     */
    @Override
    public String preViewMedia(Long mediaId) {
        if (ObjectUtils.isEmpty(mediaId)) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        Media media = this.getById(mediaId);
        if (ObjectUtils.isEmpty(media)) {
            ExceptionCast.cast(MediaErrorCode.E_140005);
        }

        // 未提交媒资不能预览
        // if (MediaAuditEnum.AUDIT_UNPAST_STATUS.getCode().equals(media.getAuditStatus())) {
        //     ExceptionCast.cast(MediaErrorCode.E_140008);
        // }

        return media.getUrl();
    }
}
